package cn.sym.basic.interceptor;

import cn.sym.basic.jwt.JwtUtils;
import cn.sym.basic.jwt.LoginData;
import cn.sym.basic.jwt.Payload;
import cn.sym.basic.jwt.RsaUtils;
import cn.sym.org.service.IEmployeeService;
import cn.sym.system.anno.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.security.PublicKey;
import java.util.List;

@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IEmployeeService employeeService;
    //spring的EL表达式
    @Value("${jwt.rsa.pub}")
    private String pubKey;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.获取请求头中的token
        String jwtToken = request.getHeader("U-TOKEN");
        //2.校验  jwtToken不能为空
        if (!StringUtils.isEmpty(jwtToken)){
            //获取到公钥
            PublicKey publicKey = RsaUtils.getPublicKey(JwtUtils.class.getClassLoader().getResource(pubKey).getFile());
            Payload<LoginData> payload = JwtUtils.getInfoFromToken(jwtToken, publicKey, LoginData.class);
            //拿不到  登录失效
            if (payload!=null){
                //还需要看当前这个人是否有权限访问资源
                LoginData loginData = payload.getLoginData();
                if (loginData.getUser()!=null){
                    //user表示前端用户，直接放行
                    return  true;
                }
                //到这一步就表示不是前端用户，就只能是后端employee，就需要校验资源的访问权限
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class);
                //判断preAuthorize是否有值,如果没有值表示是公共资源，就直接放行
                if (preAuthorize == null){
                    return  true;
                }
                //到这里就表示非公共资源，需要进行校验看是否有权限去访问
                String sn = preAuthorize.value();
                List<String> myPermissions = loginData.getPermissions();
                if (myPermissions.contains(sn)){
                    return true;
                }
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json;charset=utf-8");
                PrintWriter writer = response.getWriter();
                writer.print("{\"success\":false,\"message\":\"noPermission\"}");
                writer.flush();
                writer.close();
                //阻止放行
                return false;
            }
        }
        //这里不能直接报错，需要返回AjaxResult响应给前端，不能直接返回AjaxResult
        // 应该将AjaxResult对象 写入到response的流中
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("{\"success\":false,\"message\":\"noLogin\"}");
        writer.flush();
        writer.close();
        //阻止放行
        return false;
    }
/*
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.获取请求头中的token
        String token = request.getHeader("U-TOKEN");
        //2.校验  token不能为空
        if (!StringUtils.isEmpty(token)){
            //3.根据token的值，从redis中获取登录信息
            Object login = redisTemplate.opsForValue().get(token);
            System.out.println(login);
            //3.1 拿不到  登录失效 阻止放行
            if (login!=null){ //拿到了
                //刷新token过期时间
                redisTemplate.opsForValue().set(token,login,30, TimeUnit.MINUTES);
                Logininfo logininfo = (Logininfo) login;
                if (logininfo.getType().intValue()==1){
                    //type为1表示是前端用户，可以直接放行
                    return true;
                }
                //到这一步就表示不是前端用户，就只能是后端employee，就需要校验资源的访问权限
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class);
                //判断preAuthorize是否有值,如果没有值表示是公共资源，就直接放行
                if (preAuthorize == null){
                    return  true;
                }
                //到这里就表示非公共资源，需要进行校验看是否有权限去访问
                String sn = preAuthorize.value();
                List<String> myPermissions = employeeService.loadPermissionSnByLogininfoId(logininfo.getId());
                if (myPermissions.contains(sn)){
                    return true;
                }
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json;charset=utf-8");
                PrintWriter writer = response.getWriter();
                writer.print("{\"success\":false,\"message\":\"noPermission\"}");
                writer.flush();
                writer.close();
                //阻止放行
                return false;
            }
        }
        //这里不能直接报错，需要返回AjaxResult响应给前端，不能直接返回AjaxResult
        // 应该将AjaxResult对象 写入到response的流中
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("{\"success\":false,\"message\":\"noLogin\"}");
        writer.flush();
        writer.close();
        //阻止放行
        return false;
    }
*/
}
